import pygame, os.path, math
from shell import *

class turret_factory:
    def __init__(self, game):
        self.game = game
        files = []
        files.append(os.path.join("data", "player1.png"))
        files.append(os.path.join("data", "player2.png"))
        files.append(os.path.join("data", "player3.png"))
        files.append(os.path.join("data", "player4.png"))
        
        self.image_list = []
        self.rect_list = []
        
        for i in range(len(files)):
            images = []
            rects = []
            image_surf = pygame.image.load(files[i])
            image_rect = image_surf.get_rect()
            turr_surf = pygame.Surface((32, 32))
            turr_rect = turr_surf.get_rect()
            turr_surf.blit(image_surf, image_rect, pygame.Rect(32,0,32, 32))
            
            #we rotate 32 directions
            rot_angle = 360.0 / 32.0
            for i in range(0, 32):
                angle = float(i)*rot_angle
                new_surf = pygame.transform.rotate(turr_surf, 0-angle)
                new_rect = new_surf.get_rect()
                new_surf.set_colorkey((255, 0, 255))
                images.append(new_surf)
                rects.append(new_rect)
            self.image_list.append(images)
            self.rect_list.append(rects)
    
    def get_turret(self, number):
        newTurret = turret(self.game)
        newTurret.images = self.image_list[number]
        newTurret.rects = self.rect_list[number]
        newTurret.image = newTurret.images[0]
        newTurret.rect = newTurret.rects[0]
        return newTurret

class turret:
    def __init__(self, game):
        self.game = game
        self.images = []
        self.rects = []
        self.image = None
        self.rect = None
        self.tank = None
        
        self.posX = 400
        self.posY = 300
        self.rot = 0
        self.alpha = 255
        self.alive = True
    
    def update(self):
        if not self.tank.alive:
            self.image = pygame.Surface((1, 1))
            self.image.set_alpha(0)
            self.rect = self.image.get_rect()
            return
        if self.tank.is_local:
            self._follow_cursor()
        self.image = self.images[self.rot]
        self.image.set_alpha(self.alpha)
        self.rect = pygame.Rect(self.rects[self.rot])
        self.rect.center = (self.tank.posX, self.tank.posY)
    
    def _follow_cursor(self):
        preRot = self.rot
        (aimX, aimY) = self.game.game_logic.aimer.rect.center
        (turX, turY) = self.rect.center
        diffX = float(aimX - turX)
        diffY = float(aimY - turY)
        if not diffX == 0:
            if diffX < 0:
                adjust = -90
            else:
                adjust = 90
            realAngle = math.degrees(math.atan(diffY / diffX)) + adjust
            realAngle = realAngle % 360
            self.rot = int(math.floor(realAngle / 11.25))
        else:
            if diffY < 0:
                realAngle = 0
                self.rot = 0
            else:
                realAngle = 180
                self.rot = 16
        if not preRot == self.rot:
            self.game.game_logic.send_user_event("tur_rot", self.game.game_logic.local_player)
    
    def set_rot(self, newRot):
        self.rot = newRot
    
    def rotate_left(self):
        self.rot-= 1
        if self.rot < 0:
            self.rot = 31
    
    def rotate_right(self):
        self.rot+= 1
        if self.rot > 31:
            self.rot = 0
    
    def set_alpha(self, alpha):
        self.alpha = alpha

class tank_factory:
    def __init__(self, game, tank_list, turret_list):
        self.game = game
        self.tank_list = tank_list
        self.turret_list = turret_list
        self.turret_factory = turret_factory(self.game)
        files = []
        files.append(os.path.join("data", "player1.png"))
        files.append(os.path.join("data", "player2.png"))
        files.append(os.path.join("data", "player3.png"))
        files.append(os.path.join("data", "player4.png"))
        
        self.image_list = []
        self.rect_list = []
        
        for i in range(len(files)):
            images = []
            rects = []
            image_surf = pygame.image.load(files[i])
            image_rect = image_surf.get_rect()
            tank_surf = pygame.Surface((32, 32))
            tank_rect = tank_surf.get_rect()
            tank_surf.blit(image_surf, image_rect, pygame.Rect(0,0,32, 32))
            
            #we rotate 32 directions
            rot_angle = 360.0 / 32.0
            for i in range(0, 32):
                angle = (float(i)*rot_angle) - 90 #because the image in 90 degs off
                new_surf = pygame.transform.rotate(tank_surf, angle)
                new_rect = new_surf.get_rect()
                new_surf.set_colorkey((255, 0, 255))
                images.append(new_surf)
                rects.append(new_rect)
            self.image_list.append(images)
            self.rect_list.append(rects)
    
    def get_tank(self, number, player):
        newTank = tank(self.game, player)
        newTank.images = self.image_list[number]
        newTank.rects = self.rect_list[number]
        newTank.image = newTank.images[0]
        newTank.rect = newTank.rects[0]
        newTurret = self.turret_factory.get_turret(number)
        newTurret.tank = newTank
        newTank.turret = newTurret
        self.tank_list.append(newTank)
        self.turret_list.append(newTurret)
        self.game.game_logic.colliders.append(newTank)
        return newTank

class tank:
    def __init__(self, game, player):
        self.game = game
        self.images = []
        self.rects = []
        self.image = None
        self.rect = None
        self.turret = None
        self.is_local = False
        self.player = player
        self.health = 100
        self.assists = []
        self.killer = None
        self.ammo_full = 30
        self.ammo = self.ammo_full
        
        self.posX = 400
        self.posY = 300
        self.rot = 0
        self.speed = 0
        self.real_speed = 0
        self.slowdown = 0
        self.alive = True
        self.dead_time = 0
    
    def update(self):
        if not self.alive:
            self.dead_time+= 1
            if self.dead_time == 180:
                self.alive = True
                self.dead_time = 0
                self.posX, self.posY = self.player.start_info['start_position']
                self.health = 100
                self.ammo = self.ammo_full
                if self.is_local:
                    self.game.game_logic.ammo_bar.set_bullets(self.ammo)
                return
            self.image = pygame.Surface((1, 1))
            self.image.set_alpha(0)
            self.rect = self.image.get_rect()
            self.rect.center = (self.posX, self.posY)
            if self.is_local:
                health_perc = int(math.ceil((float(self.dead_time) / 180.0) * 100))
                self.game.game_logic.health_bar.set_health(health_perc)
            return
        rot_angle = 11.25
        degs = float(self.rot) * rot_angle
        if not self.speed == 0:
            slowdown = self.game.game_logic.map.get_slowdown_at((self.posX, self.posY))
        else:
            slowdown = 0
        if(self.speed > 0):
            x = self.posX + math.cos(math.radians(float(self.rot)*rot_angle)) * (self.speed - self.slowdown)
            y = self.posY - math.sin(math.radians(float(self.rot)*rot_angle)) * (self.speed - self.slowdown)
        else:
            x = self.posX + math.cos(math.radians(float(self.rot)*rot_angle)) * (self.speed + self.slowdown)
            y = self.posY - math.sin(math.radians(float(self.rot)*rot_angle)) * (self.speed + self.slowdown)
        if not self.speed == 0:
            slowdown = self.game.game_logic.map.get_slowdown_at((x, y))
        else:
            slowdown = 0
            
        nextRect = self.rects[self.rot]
        nextRect.center = (x, y)
        for obj in self.game.game_logic.colliders:
            if obj == self:
                continue
            if nextRect.colliderect(obj.rect):
                slowdown = 5
        if not slowdown == 5:
            self.slowdown = slowdown
        if x < self.game.game_logic.map.width and x > 0 and not slowdown == 5:
            self.posX = x
        if x < self.game.game_logic.map.width and y > 0 and not slowdown == 5:
            self.posY = y
        if self.speed > 0:
            self.real_speed = self.speed - slowdown
        if self.speed < 0:
            self.real_speed = self.speed + slowdown
        if self.speed == 0:
            self.real_speed = 0
        alpha = self.game.game_logic.map.get_alpha_at(self.rect.center)
        self.image = self.images[self.rot]
        self.image.set_alpha(alpha)
        self.turret.set_alpha(alpha)
        self.rect = pygame.Rect(self.rects[self.rot])
        self.rect.center = (self.posX, self.posY)
    
    def set_pos(self, newPos):
        (self.posX, self.posY) = newPos
        
    def set_rot(self, newRot):
        self.rot = newRot
    
    def rotate_left(self):
        self.rot+= 1
        if self.rot > 31:
            self.rot = 0
    
    def rotate_right(self):
        self.rot-= 1
        if self.rot < 0:
            self.rot = 31
    
    def forward(self):
        self.speed = 5
    
    def stop(self):
        self.speed = 0
    
    def reverse(self):
        self.speed = -5
    
    def shoot(self, target):
        if self.ammo > 0 and self.alive:
            newShell = shell(self.game, self, target, self.real_speed, self.rot * 11.25)
            self.game.game_logic.obj_list.append(newShell)
            if self.is_local:
                self.game.game_logic.ammo_bar.use_bullet()
            if self.is_local or self.game.config.host:
                self.ammo-= 1
        
    def hit(self, damage, shooter_id):
        self.assists.append(shooter_id)
        self.health = self.health - damage
        if self.health <= 0:
            self.alive = False
            self.health = 0
        
        if self.is_local:
            self.game.game_logic.health_bar.set_health(self.health)
        
        if self.health == 0 and self.game.config.host:
            self.killer = shooter_id
            misc = {}
            misc['killer'] = shooter_id
            misc['assists'] = self._get_assists()
            self.game.game_logic.send_user_event("tank_die", self.player, misc)
            self.assists = []
            
    def die(self):
        self.alive = False
    
    def load_ammo(self, count=1):
        if self.ammo < self.ammo_full:
            if (self.ammo_full - self.ammo) > count:
                self.ammo+= count
            else:
                self.ammo = self.ammo_full
            if self.is_local:
                self.game.game_logic.ammo_bar.set_bullets(self.ammo)
    
    def heal(self, count=1):
        if self.health < 100:
            if (100 - self.health) > count:
                self.health+= count
            else:
                self.health = 100
            if self.is_local:
                self.game.game_logic.health_bar.set_health(self.health)
                
    
    def _get_assists(self):
        assists = []
        for id in self.assists:
            if not id == self.killer and assists.count(id) < 1:
                assists.append(id)
        return assists
